/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       pngloader.cpp
 * Author:     karooolek
 * Created on: 2012-10-07
 *
 **********************************************************************************************************************/

#include "pngloader.h"
#include <libpng/png.h>

namespace mGameEngine
{
namespace Graphics
{

PNGLoader::PNGLoader() : ImageLoader()
{
}

PNGLoader::PNGLoader(const String &filename) : ImageLoader(filename)
{
}

PNGLoader::~PNGLoader()
{
}

void PNGLoader::load()
{
    _state = 0.0f;

    // open file
    FILE *file = fopen(_filename, "rb");
    if (!file)
    {
        return;
    }

    // check header
    uint8 header[8];
    fread(header, 1, 8, file);
    if (png_sig_cmp(header, 0, 8))
    {
        return;
    }

    // init stuff
    png_struct* png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        return;
    }
    png_info* info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        return;
    }
    png_info* end_info = png_create_info_struct(png_ptr);
    if (!end_info)
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        return;
    }
    png_init_io(png_ptr, file);
    png_set_sig_bytes(png_ptr, 8);
    
    // read header
    png_read_info(png_ptr, info_ptr);
    int width = png_get_image_width(png_ptr, info_ptr);
    int height = png_get_image_height(png_ptr, info_ptr);
    int bpp = png_get_channels(png_ptr, info_ptr) * png_get_bit_depth(png_ptr, info_ptr);

    // read data
    uint8 *data = new uint8[width * height * bpp / 8];
    uint8 **row_pointers = new (uint8 *[height]);
    for(int y = 0; y != height; ++y)
    {
        row_pointers[height - 1 - y] = data + y  * width * bpp / 8;
    }
    png_read_image(png_ptr, row_pointers);
    delete[] row_pointers;

    // create image
    _image = new Image((uint8 *)data, width, height, bpp);

    // close file
    fclose(file);
    delete[] data;

    _state = 1.0;
}

}
}
